using System;
using System.Collections.Generic;
using System.ComponentModel;

using CureConsulting;
using CureConsulting.Business;

using Blog.Net.Common.DataObjects;

namespace Blog.Net.Business.BusinessObjects
{
	/// <summary>
	/// Business Object for blog_entry.
	/// </summary>
	public partial class BlogEntryBO : BusinessObjectBase
	{
		#region Constructors

		/// <summary>
		/// Create a BlogEntryBO object
		/// </summary>
		public BlogEntryBO()
		{
			this.blogEntry = new BlogEntry();
		}

		/// <summary>
		/// Create a BlogEntryBO object
		/// </summary>
		public BlogEntryBO(int id) : this()
		{
			this.blogEntry.Id = id;
		}
		
		/// <summary>
		/// Create a BlogEntryBO object
		/// </summary>
		/// <param name="subject"></param>
		/// <param name="subhead"></param>
		/// <param name="body"></param>
		/// <param name="views"></param>
		/// <param name="points"></param>
		/// <param name="votes"></param>
		/// <param name="createDate"></param>
		public BlogEntryBO( string subject, string subhead, string body, decimal views, int points, int votes, DateTime createDate ) : this()
		{
			this.blogEntry.Subject = subject;
			this.blogEntry.Subhead = subhead;
			this.blogEntry.Body = body;
			this.blogEntry.Views = views;
			this.blogEntry.Points = points;
			this.blogEntry.Votes = votes;
			this.blogEntry.CreateDate = createDate;
		}

		/// <summary>
		/// Create a BlogEntryBO object
		/// </summary>
		/// <param name="BlogEntry"></param>
		public BlogEntryBO(BlogEntry blogEntry)
		{
			if(blogEntry != null)
			{
				this.blogEntry = blogEntry;
			}
			else
			{
				throw new ArgumentNullException();
			}
		}
		
		#endregion
		
		#region Member Variables
		
		private BlogEntry blogEntry;
		
		protected SortableBindingList<BlogResponseBO> _blogResponses;
		protected SortableBindingList<BlogCategoryBO> _blogCategories;
		
		#endregion
		
		#region Private Methods
		
		void _blogResponses_ListChanged(object sender, ListChangedEventArgs e)
        {
            switch (e.ListChangedType)
            {
                case ListChangedType.ItemAdded:
                    if (_blogResponses[e.NewIndex] != null)
                    {
                        POCO.BlogResponses.Insert(e.NewIndex, BlogResponses[e.NewIndex].POCO);
                    }
                    break;

                case ListChangedType.ItemDeleted:
                    POCO.BlogResponses.RemoveAt(e.NewIndex);
                    break;

                default:
                    break;
            }
        }
		
		
		void _blogCategories_ListChanged(object sender, ListChangedEventArgs e)
        {
            switch (e.ListChangedType)
            {
                case ListChangedType.ItemAdded:
                    if (_blogCategories[e.NewIndex] != null)
                    {
                        POCO.BlogCategories.Insert(e.NewIndex, _blogCategories[e.NewIndex].POCO);
                    }
                    break;

                case ListChangedType.ItemDeleted:
					POCO.BlogCategories.RemoveAt(e.NewIndex);
                    break;
					
				case ListChangedType.Reset:
                    POCO.BlogCategories.Clear();
                    break;

                default:
                    break;
			}
        }
		
		
		#endregion
		
		#region Public Properties
		
		/// <summary>
        /// Property for POCO
        /// </summary>
        public BlogEntry POCO
        {
            get { return blogEntry; }
        }
		
		/// <summary>
        /// Property for Id
        /// </summary>
        public override int? Id
        {
            get { return blogEntry.Id; }
			set
			{
				if(value.HasValue)
					blogEntry.Id = value;
			}
        }
		
		/// <summary>
		/// BlogEntry Subject
		/// </summary>
		public virtual string Subject
		{
			get { return blogEntry.Subject; }
			set
			{
				blogEntry.Subject = value;
				NotifyPropertyChanged("Subject");
			}
		}

		/// <summary>
		/// BlogEntry Subhead
		/// </summary>
		public virtual string Subhead
		{
			get { return blogEntry.Subhead; }
			set
			{				
				blogEntry.Subhead = (value != null && value.Length > 0) ? value : null;
				NotifyPropertyChanged("Subhead");
			}
		}

		/// <summary>
		/// BlogEntry Body
		/// </summary>
		public virtual string Body
		{
			get { return blogEntry.Body; }
			set
			{
				blogEntry.Body = value;
				NotifyPropertyChanged("Body");
			}
		}

		/// <summary>
		/// BlogEntry Views
		/// </summary>
		public virtual decimal Views
		{
			get { return blogEntry.Views; }
			set
			{
				blogEntry.Views = value;
				NotifyPropertyChanged("Views");
			}
		}

		/// <summary>
		/// BlogEntry Points
		/// </summary>
		public virtual int Points
		{
			get { return blogEntry.Points; }
			set
			{
				blogEntry.Points = value;
				NotifyPropertyChanged("Points");
			}
		}

		/// <summary>
		/// BlogEntry Votes
		/// </summary>
		public virtual int Votes
		{
			get { return blogEntry.Votes; }
			set
			{
				blogEntry.Votes = value;
				NotifyPropertyChanged("Votes");
			}
		}

		/// <summary>
		/// BlogEntry CreateDate
		/// </summary>
		public virtual DateTime CreateDate
		{
			get { return ConvertDateTimeFromDB(blogEntry.CreateDate); }
			set
			{
				blogEntry.CreateDate = ConvertDateTimeToDB(value);
				NotifyPropertyChanged("CreateDate");
			}
		}

		/// <summary>
		/// BlogEntry BlogResponses
		/// </summary>
		public virtual SortableBindingList<BlogResponseBO> BlogResponses
		{
			get
			{
				if(_blogResponses == null)
				{			
					SortableBindingList<BlogResponseBO> retVal = new SortableBindingList<BlogResponseBO>();

					if (blogEntry.BlogResponses != null)
					{
						foreach (BlogResponse tempBlogResponse in blogEntry.BlogResponses)
						{
							retVal.Add(new BlogResponseBO(tempBlogResponse));
						}
					}
		
					_blogResponses = retVal;
					_blogResponses.ListChanged += new ListChangedEventHandler(_blogResponses_ListChanged);
				}
				
				return _blogResponses;
			}
		}
		
		/// <summary>
		/// BlogEntry BlogCategories
		/// </summary>
		[ManyToMany]
		public virtual SortableBindingList<BlogCategoryBO> BlogCategories
		{
			get
			{
				if(_blogCategories == null)
				{			
					SortableBindingList<BlogCategoryBO> retVal = new SortableBindingList<BlogCategoryBO>();

					if (blogEntry.BlogCategories != null)
					{
						foreach (BlogCategory tempBlogCategory in blogEntry.BlogCategories)
						{
							retVal.Add(new BlogCategoryBO(tempBlogCategory));
						}
					}
		
					_blogCategories = retVal;
					_blogCategories.ListChanged += new ListChangedEventHandler(_blogCategories_ListChanged);
				}
				
				return _blogCategories;
			}
		}

		
		/// <summary>
        /// Property for Dirty
        /// </summary>
        public override bool Dirty
        {
            get { return blogEntry.Dirty; }
        }
		
		/// <summary>
        /// Property for IsNew
        /// </summary>
        public override bool IsNew
        {
            get { return blogEntry.IsNew; }
        }
		
		#endregion
		
		#region Public Methods
		
		/// <summary>
		/// Update a BlogEntryBO object
		/// </summary>
		public void UpdateBO(BlogEntry blogEntry)
		{
			this.blogEntry.Id = blogEntry.Id;
			this.blogEntry.Subject = blogEntry.Subject;
			this.blogEntry.Subhead = blogEntry.Subhead;
			this.blogEntry.Body = blogEntry.Body;
			this.blogEntry.Views = blogEntry.Views;
			this.blogEntry.Points = blogEntry.Points;
			this.blogEntry.Votes = blogEntry.Votes;
			this.blogEntry.CreateDate = blogEntry.CreateDate;
		}
		
		/// <summary>
		/// Override Equals to compare object properties.
		/// Note that child collections are ignored to avoid performance issues
		/// and possible circular references. Any DateTime properties will be considered equal
		/// if they differ by less than a second.  This is necessary because the RDBMS datetime data type
		/// (on Oracle or Sql Server) has less precision than the .Net DateTime struct.
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public override bool Equals(object obj)
		{
			if(obj == null || obj.GetType() != this.GetType()) { return false; }
			
			if(Object.ReferenceEquals(this, obj)) { return true; }
			
			BlogEntryBO other = (BlogEntryBO)obj;

			return
			(
				this.Id == other.Id
				&& this.Subject == other.Subject
				&& this.Subhead == other.Subhead
				&& this.Body == other.Body
				&& this.Views == other.Views
				&& this.Points == other.Points
				&& this.Votes == other.Votes
				&& this.CreateDate.Subtract(other.CreateDate).Duration().Ticks < TimeSpan.TicksPerSecond
			);
			
		}
		
		/// <summary>
		/// This class is mutable and therefore should not be used as a Hashtable key.
		/// GetHashCode will return the same value for all instances of this class.
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode()
		{
			return base.GetHashCode();
		}

		/// <summary>
		/// Reset the dirty flag
		/// </summary>
		public override void ResetDirty()
		{
			blogEntry.ResetDirty();
		}
		
		#endregion
	}
}